﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace Erau.ERBParser
{
    /// <summary>
    /// ERB 파일 읽을 때 참고할 구문들
    /// - ;는 주석 명령어이므로, 이 뒤에 오는 내용은 무시해야 함. 이건 라인 첫 칸에만 붙을 수 있는 게 아니므로 라인 읽을때 체크할지는 생각해봐야 함.
    /// - [xxx] 형태로 된 라인은 스크립트에서 지정된 특수 블록. [IF_DEGUG]나 [IF XXX]~[ENDIF] 같은. 후자는 #ifdef 같은 기능을 하는듯.
    /// #로 시작하는 라인도 특수한 정의용(#DEFINE, #NO, #DIM 등)으로 사용됨. DEFINE말고는 안 써도 될 것 같지만. 저거 하나 때문에라도 넣어야 할 듯.
    ///  함수 선언 바로 아래에 #FUNCTION을 선언하면 그 함수가 반환값이 있는 함수로 취급된다고 함. 이 기능은 안 써도 될 것 같다.
    /// @로 시작하는 라인은 함수 정의. 구조상 무조건 구현해줘야 하는 함수도 몇 개 있는 것 같지만, 일단 신경쓰지 말자.
    /// http://sourceforge.jp/projects/emuera/wiki/EmuDic
    /// http://sourceforge.jp/projects/emuera/wiki/exfunc#h3-.E7.89.B9.E6.AE.8A.E3.81.AA.E3.83.96.E3.83.AD.E3.83.83.E3.82.AF.E3.82.92.E8.A1.A8.E3.81.99.E8.A1.8C
    /// http://sourceforge.jp/projects/emuera/wiki/FrontPage
    /// </summary>
    public class ERBLoader
    {
		/// <summary>
		/// erb 스크립트 파일 로드.
		/// </summary>
		public void loadErb(string filepath, string filename)
		{
			ErbStreamReader reader = null;
			ScriptFunction currentFunction = null;
			InstructionLine prevLine = null;
			StringBuffer str;
			ScriptPosition pos = null;

			try
			{
				// 파일 읽기에 실패하면 예외가 날아가니까 catch에서 체크한다.
				reader = new ErbStreamReader(filepath + @"\" + filename);

				//반복 

				// { } 구문을 감안한 실제 라인 한 줄을 읽는다.
				while (!((str = reader.ReadLine()).Empty))
				{
					// 현재 스크립트 파일 위치 기록. 에러표시 등에 사용됨.
					pos = new ScriptPosition(filename, reader.Line, str.Buffer);

					if (str.Current == '[' && str.Next != '[') // [] 특수블록 처리. 일단 무시.
					{

					}

					else if (str.Current == '#') // # 특수 명령 라인 처리. 역시 일단 무시.
					{

					}
					else if (str.Current == '@') // @로 시작하는 라인은 함수임.
					{
						// 함수 객체 생성하고 현재 함수로 지정.
						// 다음 함수가 지정되거나 erb 파일이 끝날 때까지 이 다음부터 읽는 라인은 모두 이 함수에 속함.
						currentFunction = new ScriptFunction(str, pos);


					}
					else // 그 외의 경우 일반 문법
					{
						// 일반 문장이 나왔을 때 지정된 함수가 없다면 스크립트가 잘못된 것.
						if (currentFunction == null) throw new Exception("함수에 속하지 않은 라인");

						InstructionLine t = Parser.ParseLine(str, currentFunction, pos);
						currentFunction.Instructions.Add(t);

						if (prevLine != null) prevLine.NextLine = t;
					}
				}
			}
			catch (Exception ex)
			{

			}
			finally
			{
				if(reader != null)
					reader.Close();

				// 메모리 누수를 막기 위해 연결된 객체를 모두 해제.
				reader = null;
				currentFunction = null;
				prevLine = null;
				str = null;
			}
			return;
		}




    }
}
